package dk.aiszone.lang.messer;

import japa.parser.ParseException;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.Javac;
import org.apache.tools.ant.taskdefs.optional.junit.JUnitTask;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.ant.util.FileUtils;

import dk.aiszone.lang.autosource.generatorobjects.InterfaceBody;
import dk.aiszone.lang.autosource.generatorobjects.JavaFile;

/**
 * Runs JUnit tests.
 */
public class SourceMesser extends Task {

    private Path classpath;
    private FileSet fs;
    private JUnitTask junitTask;
    private Javac javacTask;
    private JavaFile baseFile;

    /**
     * Add a <code>FileSet</code> containing the files to be modified.
     * 
     * @param fs
     *            <code>FileSet</code> containing the files to modify.
     */
    public void addFileSet(FileSet fs) {
        this.fs = fs;
    }

    @SuppressWarnings("unchecked")
    @Override
    public void execute() throws BuildException {
        log("Running initial test... Must pass in order for the SourceMesser to continue");
        // Start by validating that the tests work before we modify the source.
        this.junitTask.execute();

        for (Iterator<FileResource> iterator = fs.iterator(); iterator.hasNext();) {
            FileResource fileResource = iterator.next();
            try {
                doMe(fileResource);
            } catch (ParseException e) {
                throw new BuildException("File " + fileResource.getFile().getAbsolutePath() + " not in a valid", e);
            }
        }
    }

    private void doMe(FileResource fileResource) throws ParseException {
        baseFile = new MesserSourceFileParser(fileResource.getFile().getAbsolutePath()).getResultingJavaFile();
        if (baseFile.getMainClass() instanceof InterfaceBody) { // We don't mess with interfaces.
            return;
        }

        FileMesser messer = new FileMesser(baseFile);
        while(messer.hasNext()) {
            JavaFile messed = messer.next();
        }
        
        // compile

        try {
            this.junitTask.execute();
        } catch (BuildException ex) {
            if (ex.getMessage().contains("failed")) {

            }
        }

    }

    private void copySourceToTmp(FileResource fileResource) throws IOException {

    }

    /**
     * Set the classpath to be used for this compilation.
     * 
     * @param classpath
     *            an Ant Path object containing the compilation classpath.
     */
    public void setClasspath(Path classpath) {
        if (classpath == null) {
            this.classpath = classpath;
        } else {
            this.classpath.append(classpath);
        }
    }

    /**
     * Adds a reference to a classpath defined elsewhere.
     * 
     * @param r
     *            a reference to a classpath
     */
    public void setClasspathRef(Reference r) {
        createClasspath().setRefid(r);
    }

    public void setJunit(JUnitTask junitTask) {
        this.junitTask = junitTask;
        this.junitTask.setFork(true);
        this.junitTask.setOutputToFormatters(false);
        this.junitTask.setHaltonerror(true);
        this.junitTask.setHaltonfailure(true);
    }

    public void setJavac(Javac javacTask) {
        this.javacTask = javacTask;

    }

    private Path createClasspath() {
        if (classpath == null) {
            classpath = new Path(getProject());
        }
        return classpath.createPath();
    }
}